package com.zmn.oms.admin.controller.sync;

import com.google.common.collect.Lists;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.oms.admin.controller.OmsBaseController;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.constant.OrderStatusConsts;
import com.zmn.oms.common.dto.ResultDTO;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.oms.zmn.business.interfaces.work.autoflow.WorkFlowContextBService;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SourceFilter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static com.zmn.common.utils.date.DateUtil.FORMAT_DATE;


/**
 * 类描述：自动算账同步
 * @author heciqi
 * @date 2021/8/3 17:19
 */
@Slf4j
@RequestMapping("/sync")
@RestController
public class SyncAutoAccountController extends OmsBaseController {
    @Autowired
    private OrderWorkEsBService orderWorkEsBService;
    @Autowired
    private WorkFlowContextBService workFlowContextBService;

    @GetMapping(value = "/completecheckout")
    public ResultDTO completeCheckout(String startTime, String endTime) {
        log.info("SyncAutoAccountController#completeCheckout入参：{}-{}", startTime, endTime);
        if (StringUtil.isBlank(startTime) || StringUtil.isBlank(endTime)) {
            return ResultDTO.success("参数有误");
        }
        new Thread(() -> {
            log.info("线程执行--->");
            runAutoAccount(startTime, endTime);
        }).start();

        return ResultDTO.success("自动收单算账任务--提交成功");
    }

    private void runAutoAccount(String startTime, String endTime) {
        Date dtStartTime = DateUtil.parse(startTime, FORMAT_DATE);
        Date dtEndTime = DateUtil.parse(endTime, FORMAT_DATE);
        while (dtStartTime.getTime() <= dtEndTime.getTime()) {
            String queryStartTime = DateUtil.toString(dtStartTime, FORMAT_DATE + " 00:00:00");
            String queryEndTime = DateUtil.toString(dtStartTime, FORMAT_DATE + " 23:59:59");
            List<EsOrderWork> newEsOrderWorks = this.listWork(queryStartTime, queryEndTime, Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW));
            if (CollectionUtil.isNotNullOrEmpty(newEsOrderWorks)) {
                for (EsOrderWork esOrderWork : newEsOrderWorks) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage(),e);
                    }
                    workFlowContextBService.asyncAutoFlow(esOrderWork.getId(), esOrderWork.getOrderId());
                }
            }
            dtStartTime = DateUtil.addDays(dtStartTime, 1);
        }

        Date dtStartTime2 = DateUtil.parse(startTime, FORMAT_DATE);
        Date dtEndTime2 = DateUtil.parse(endTime, FORMAT_DATE);
        while (dtStartTime2.getTime() <= dtEndTime2.getTime()) {
            String queryStartTime = DateUtil.toString(dtStartTime2, FORMAT_DATE + " 00:00:00");
            String queryEndTime = DateUtil.toString(dtStartTime2, FORMAT_DATE + " 23:59:59");
            List<EsOrderWork> reworkAndRefundEsOrderWorks = this.listWork(queryStartTime, queryEndTime, Lists.newArrayList(OrderConsts.ORDER_TYPE_REWORK, OrderConsts.ORDER_TYPE_REFUND));
            if (CollectionUtil.isNotNullOrEmpty(reworkAndRefundEsOrderWorks)) {
                for (EsOrderWork esOrderWork : reworkAndRefundEsOrderWorks) {
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage(),e);
                    }
                    workFlowContextBService.asyncAutoFlow(esOrderWork.getId(), esOrderWork.getOrderId());
                }
            }
            dtStartTime2 = DateUtil.addDays(dtStartTime2, 1);
        }
    }

    @GetMapping(value = "/completecheckoutbyorderid")
    public ResultDTO completeCheckoutByOrderId(String orderIds) {
        log.info("SyncAutoAccountController#completeCheckoutByOrderId：{}", orderIds);
        if (StringUtil.isBlank(orderIds)) {
            return ResultDTO.success("参数有误");
        }

        String[] arrOrderIds = orderIds.split(",");
        for (String s : arrOrderIds) {
            workFlowContextBService.asyncAutoFlow(Long.parseLong(s), Long.parseLong(s));
        }
        return ResultDTO.success("自动收单算账任务--提交成功");
    }

    private List<EsOrderWork> listWork(String startTime, String endTime,List<Integer> types) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.filter(QueryBuilders.rangeQuery("receiveTime").gte(startTime).lte(endTime));
        queryBuilder.filter(QueryBuilders.termsQuery("status",
                Arrays.asList(OrderStatusConsts.WORK_STATUS_COMPLETE, OrderStatusConsts.WORK_STATUS_CHECKOUT
                )));
        queryBuilder.filter(QueryBuilders.termsQuery("type", types));
        NativeSearchQuery searchQuery = new NativeSearchQuery(queryBuilder);
        searchQuery.setPageable(PageRequest.of(0, 10000));
        String[] columns = {"id", "orderId"};
        SourceFilter sourceFilter = new FetchSourceFilter(columns, null);
        searchQuery.addSourceFilter(sourceFilter);
        List<EsOrderWork> page = orderWorkEsBService.listPageByQuery(searchQuery);
        log.info("自动算账同步startTime:{}，endTime:{}查询es：{}，条数:{}", startTime, endTime, searchQuery, page.size());
        return page;
    }
}
